package tardistv.view;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.util.ArrayList;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.SwingUtilities;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import tardistv.controller.Controller;
import tardistv.controller.ListShowDownloadedListener;
import tardistv.controller.ShowFilledWithEpisodesListener;
import tardistv.model.EpisodeTableModel;
import tardistv.model.ListShowDownloadedEvent;
import tardistv.model.Show;
import tardistv.model.ShowFilledWithEpisodesEvent;

/**
 * Main window of the application
 * @author Carballude
 */
public class MainWindow extends JFrame implements ListShowDownloadedListener, ShowFilledWithEpisodesListener {

    private Controller controller;
    private ArrayList<Show> subscribedShows;

    private JMenuBar menuBar;
    private JMenu menuFile;
    private JMenuItem itemExit;

    private JPanel panelStatusBar;
    private JPanel panelCentral;
    private JScrollPane scrollPaneSubscriptions;
    private JScrollPane scrollPaneEpisodes;
    
    private JLabel lbStatusBar;

    private JList listSubscriptions;

    private JTable tableEpisodes;
    private EpisodeTableModel episodeTableModel;

    public MainWindow() {
        controller = Controller.getInstance();
        controller.addListShowDownloadedListener(this);
        controller.addShowFilledWithEpisodesListener(this);
        subscribedShows = controller.getSubscribedShows();
        this.setTitle("Tardis TV");
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.getContentPane().setLayout(new BorderLayout());
        this.add(getBarMenu(), BorderLayout.NORTH);
        this.add(getPanelCentral(),BorderLayout.CENTER);
        this.add(getPanelStatusBar(), BorderLayout.SOUTH);
        this.setSize(640, 480);
        this.setVisible(true);        
        if (subscribedShows.isEmpty()) {
            lbStatusBar.setText("Downloading list of shows...");
            controller.startDownloadingListShow();
        }
    }

    private JPanel getPanelCentral(){
        if(panelCentral==null){
            panelCentral=new JPanel(new BorderLayout());
            panelCentral.add(getScrollPaneSubscriptions(),BorderLayout.WEST);
            panelCentral.add(getScrollPaneEpisodes(),BorderLayout.CENTER);
        }
        return panelCentral;
    }

    private JScrollPane getScrollPaneEpisodes(){
        if(scrollPaneEpisodes==null){
            scrollPaneEpisodes=new JScrollPane(getTableEpisodes());
        }
        return scrollPaneEpisodes;
    }

    EpisodeTableModel getEpisodeTableModel(){
        if(episodeTableModel==null){
            episodeTableModel = new EpisodeTableModel();
        }
        return episodeTableModel;
    }

    private JTable getTableEpisodes(){
        if(tableEpisodes==null){
            tableEpisodes=new JTable(getEpisodeTableModel());
        }
        return tableEpisodes;
    }

    private JScrollPane getScrollPaneSubscriptions(){
        if(scrollPaneSubscriptions==null){
            scrollPaneSubscriptions=new JScrollPane(getListSubscriptions());
        }
        return scrollPaneSubscriptions;
    }

    JList getListSubscriptions(){
        if(listSubscriptions==null){
            listSubscriptions = new JList(subscribedShows.toArray());
            listSubscriptions.setPreferredSize(new Dimension(125, 200));
            listSubscriptions.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
            listSubscriptions.addListSelectionListener(new ListSelectionListener() {

                @Override
                public void valueChanged(ListSelectionEvent e) {
                    getEpisodeTableModel().showNewShow(controller.getEpisodesForShow((Show)listSubscriptions.getSelectedValue()));
                    lbStatusBar.setText("Updating information of " + ((Show)listSubscriptions.getSelectedValue()).getName() + "...");
                }
            });
        }
        return listSubscriptions;
    }

    private JMenuBar getBarMenu() {
        if (menuBar == null) {
            menuBar = new JMenuBar();
            menuBar.add(getMenuFile());
        }
        return menuBar;
    }

    private JMenu getMenuFile() {
        if (menuFile == null) {
            menuFile = new JMenu("File");
            menuFile.setMnemonic('f');
            menuFile.add(getItemExit());
        }
        return menuFile;
    }

    private JMenuItem getItemExit() {
        if (itemExit == null) {
            itemExit = new JMenuItem("Exit");
            itemExit.setMnemonic('e');
        }
        return itemExit;
    }

    JLabel getLabelStatusBar() {
        if (lbStatusBar == null) {
            lbStatusBar = new JLabel("Ready!");
        }
        return lbStatusBar;
    }

    private JPanel getPanelStatusBar() {
        if (panelStatusBar == null) {
            panelStatusBar = new JPanel(new FlowLayout(FlowLayout.LEFT));
            panelStatusBar.add(getLabelStatusBar());
        }
        return panelStatusBar;
    }

    /**
     * This method will be fired every single time the list of available shows is downloaded
     * @param event Event with all the pertinent information
     */
    @Override
    public void listShowsDownloaded(final ListShowDownloadedEvent event) {
        final MainWindow frame = this;
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                new SubscribeDialog(frame, event.getShows());
            }
        });
    }

    @Override
    public void showFilledWithEpisodes(final ShowFilledWithEpisodesEvent event) {
        final MainWindow frame = this;
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                if(((Show)frame.getListSubscriptions().getSelectedValue()).getCode().compareTo(event.getShow().getCode())==0)
                    episodeTableModel.showNewShow(event.getShow());
                frame.getLabelStatusBar().setText("Updated episodes for " + event.getShow().getName());
            }
        });
    }
}
